package com.qdlc.p2p.biz.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.qdlc.p2p.biz.service.UserRedEnvelopeService;
import com.qdlc.p2p.common.util.BeanCopierUtils;
import com.qdlc.p2p.common.util.BigDecimalUtil;
import com.qdlc.p2p.common.util.DateUtil;
import com.qdlc.p2p.dal.common.SystemConfigHelper;
import com.qdlc.p2p.dal.common.SystemConfigHelper.Nid;
import com.qdlc.p2p.dal.common.model.jpa.PageDataList;
import com.qdlc.p2p.dal.dao.RedEnvelopeAttachedDao;
import com.qdlc.p2p.dal.dao.RedEnvelopeDao;
import com.qdlc.p2p.dal.dao.UserDao;
import com.qdlc.p2p.dal.dao.UserRedEnvelopeDao;
import com.qdlc.p2p.dal.dto.BondTender;
import com.qdlc.p2p.dal.dto.BorrowTender;
import com.qdlc.p2p.dal.dto.RedEnvelope;
import com.qdlc.p2p.dal.dto.RedEnvelopeAttached;
import com.qdlc.p2p.dal.dto.User;
import com.qdlc.p2p.dal.dto.UserRedEnvelope;
import com.qdlc.p2p.dal.model.RedEnvelopeModel;
import com.qdlc.p2p.dal.model.UserRedEnvelopeModel;

/**
 * 用户红包获取记录Service
 *
 * @author ylx
 * @version 2.0
 * @date 2015年4月22日 下午3:46:19
 */
@Service("userRedEnvelopeService")
public class UserRedEnvelopeServiceImpl implements UserRedEnvelopeService {

    private static Logger logger = Logger.getLogger(UserRedEnvelopeServiceImpl.class);

    @Resource
    private UserRedEnvelopeDao userRedEnvelopeDao;

    @Resource
    private RedEnvelopeAttachedDao envelopeAttachedDao;

    @Resource
    private RedEnvelopeDao redEnvelopeDao;

    @Resource
    private UserDao userDao;

    private static String WEB_URL = SystemConfigHelper.getValue(Nid.WEB_URL);

    static {
        WEB_URL = WEB_URL.replace("http:", "").replace("https:", "");
    }

    @Override
    public UserRedEnvelope save(UserRedEnvelope userRedEnvelope) {
        return userRedEnvelopeDao.save(userRedEnvelope);
    }

    @Override
    public PageDataList<UserRedEnvelopeModel> list(UserRedEnvelopeModel model) {
        return userRedEnvelopeDao.list(model);
    }

    @SuppressWarnings("static-access")
    @Override
    public UserRedEnvelope giveRedEnvelope(long toUserId, long redEnvelopeId, String sourceType) {
        //获取用户
        User user = userDao.find(toUserId);
        if (null == user) {
            logger.info("用户不存在，用户id:" + toUserId);
            return null;
        }
        //获取红包方案
        RedEnvelope redEnvelope = redEnvelopeDao.find(redEnvelopeId);
        if (null == redEnvelope) {
            logger.info("红包方案不存在，红包ID:" + redEnvelopeId);
            return null;
        }
        RedEnvelopeModel model = RedEnvelopeModel.instance(redEnvelope);

        // 检测红包常规属性
        boolean checkResult = model.checkUseModel();
        if (!checkResult) {
            return null;
        }
        // 如果发放方式不是固定金额则返回null
        if (model.RED_ENVELOPE_PAY_FIXED_AMOUNT != model.getPayType()) {
            return null;
        }

        // 如果红包金额大于0则发放红包
        if (model.getAmount() > 0) {
            UserRedEnvelope userRedEnvelopen = new UserRedEnvelope(user,
                    model.getName(), model.getAmount(), model.getType(),
                    model.getValidDay(), sourceType);

            // 更新红包已发放数量
            redEnvelope.setLssueNum(redEnvelope.getLssueNum() + 1);
            redEnvelopeDao.update(redEnvelope);

            return userRedEnvelopeDao.save(userRedEnvelopen);
        }
        return null;
    }

    /**
     * 计算红包发放金额
     *
     * @param money 用户操作金额
     * @param model 红包方案
     * @return
     */
    @SuppressWarnings("static-access")
    public double calculationAmount(double money, RedEnvelopeModel model) {
        // 红包发放金额
        double amount = 0;
        // 红包最小金额
        double minAmount = model.getMinAmount();
        // 红包最大金额
        double maxAmount = model.getMaxAmount();

        // 发放方式为固定金额
        if (model.RED_ENVELOPE_PAY_FIXED_AMOUNT == model.getPayType()) {
            amount = model.getAmount();
            // 如果发放为固定金额则直接返回结果，不需要执行下面操作
            return amount;
        }

        // 发放方式为固定比率
        if (model.RED_ENVELOPE_PAY_FIXED_RATE == model.getPayType()) {
            amount = BigDecimalUtil.mul(money, model.getRate() / 100);
        }

        // 发放方式为区间金额
        if (model.RED_ENVELOPE_PAY_INTERVAL_AMOUNT == model.getPayType()) {
            amount = calculationIntervalAmount(money, model);
            // 如果发放为固定金额则直接返回结果，不需要执行下面操作
            return amount;
        }

        // 发放方式为区间比率
        if (model.RED_ENVELOPE_PAY_INTERVAL_RATE == model.getPayType()) {
            amount = calculationIntervalAmount(money, model);
        }

        //如果配置有红包最大与最小上限，则根据计算的红包金额进行处理
        if (amount > 0 && minAmount > 0 && amount < minAmount) {
            amount = minAmount;
        }

        if (amount > 0 && maxAmount > 0 && amount > maxAmount) {
            amount = maxAmount;
        }
        // 红包金额取整
        amount = BigDecimalUtil.round(amount, 0);
        return amount;
    }

    /**
     * 计算区间红包金额
     *
     * @param money 操作金额
     * @param model 红包方案
     * @return
     */
    @SuppressWarnings("static-access")
    public double calculationIntervalAmount(double money, RedEnvelopeModel model) {
        double amount = 0;
        // 获取红包附属区间集合
        List<RedEnvelopeAttached> list = envelopeAttachedDao.list(model.getId());

        // 计算红包金额
        for (int i = 0; i < list.size(); i++) {
            RedEnvelopeAttached attached = list.get(i);
            if (i == list.size() - 1) {
                // 最后一档不限
                if (attached.getMin() <= money) {
                    if (model.RED_ENVELOPE_PAY_INTERVAL_AMOUNT == model.getPayType()) {
                        amount = attached.getAmount();
                    } else {
                        amount = BigDecimalUtil.mul(money, attached.getRate() / 100);
                    }
                    break;
                }
            } else {
                if (attached.getMin() <= money && attached.getMax() > money) {
                    if (model.RED_ENVELOPE_PAY_INTERVAL_AMOUNT == model.getPayType()) {
                        amount = attached.getAmount();
                    } else {
                        amount = BigDecimalUtil.mul(money, attached.getRate() / 100);
                    }
                }
            }
        }
        return amount;
    }

    @Override
    public UserRedEnvelope update(UserRedEnvelope userRedEnvelope) {
        return userRedEnvelopeDao.update(userRedEnvelope);
    }

    @Override
    public void doInvalid(long id) {
        userRedEnvelopeDao.doInvalid(id);
    }

    @Override
    public List<UserRedEnvelopeModel> useableList(long userId) {
    	List<UserRedEnvelope> list = userRedEnvelopeDao.useableList(userId);
    	if(list == null){
    		return Collections.emptyList();
    	}
    	List<UserRedEnvelopeModel> modelList = new ArrayList<UserRedEnvelopeModel>(list.size());
        for (UserRedEnvelope userRedEnvelope : list) {
            UserRedEnvelopeModel userRedEnvelopeModel = new UserRedEnvelopeModel();
            BeanCopierUtils.copyProperties(userRedEnvelope, userRedEnvelopeModel);
            int remainDays = DateUtil.daysBetween(DateUtil.getNow(), userRedEnvelope.getExpiredTime());
            userRedEnvelopeModel.setRemainDays(remainDays);
            modelList.add(userRedEnvelopeModel);
        }
        return modelList;
    }

    @Override
    public double getTotalAmountByIds(long[] ids, long toUserId) {
        return userRedEnvelopeDao.getTotalAmountByIds(ids, toUserId);
    }

    @Override
    public double getTenderUseAmount(long tenderId) {
        return userRedEnvelopeDao.getTenderUseAmount(tenderId);
    }

    @Override
    public void tenderBorrowFreezeRedEnvelope(BorrowTender borrowTender, long[] redEnvelopeIds) {
        userRedEnvelopeDao.tenderBorrowFreezeRedEnvelope(borrowTender, redEnvelopeIds);
    }

    @Override
    public void tenderBorrowUseRedEnvelope(long tenderId) {
        userRedEnvelopeDao.tenderBorrowUseRedEnvelope(tenderId);
    }

    @Override
    public void tenderBorrowFailUseRedEnvelope(BorrowTender borrowTender) {
        userRedEnvelopeDao.tenderBorrowFailUseRedEnvelope(borrowTender);
    }

    @Override
    public double getTotalAmountByUseTypeANdKeyId(String useType, long keyId) {
        return userRedEnvelopeDao.getTotalAmountByUseTypeANdKeyId(useType, keyId);
    }

    @Override
    public void tenderBondUseRedEnvelope(BondTender bondTender, long[] redEnvelopeIds) {
        userRedEnvelopeDao.tenderBondUseRedEnvelope(bondTender, redEnvelopeIds);
    }

    @Override
    public void tenderBondFailUseRedEnvelope(BondTender bondTender) {
        userRedEnvelopeDao.tenderBondFailUseRedEnvelope(bondTender);
    }

    @Override
    public int userableCount(long userId) {
        return userRedEnvelopeDao.userableCount(userId);
    }

    @Override
    public boolean checkRedEnvelope(long[] redEnvelopeIds, User user) {
        return userRedEnvelopeDao.checkRedEnvelope(redEnvelopeIds, user);
    }

    @Override
    public double[] getUseRedEnvelopeSumByStatus(int status, String year) {
        double[] amounts = new double[12];
        String date;
        for (int i = 0; i < 12; i++) {
            date = year + (i > 8 ? "-" : "-0") + (i + 1);
            amounts[i] = userRedEnvelopeDao.getUseRedEnvelopeSumByStatus(status, date);
        }
        return amounts;
    }
    @Override
    public void redEnvelopeExpireDispose() {
        userRedEnvelopeDao.redEnvelopeExpireDispose();
    }
}
